package pojo;

import java.util.LinkedHashMap;
import java.util.Map;

public abstract class AI {
    protected int[][] map;//棋盘
    protected int N;//棋盘大小
    protected int color;//ai方颜色
    protected int x=-1;//ai要下的坐标
    protected int y=-1;//ai要下的坐标
    protected int chess;//ai棋子id
    protected int chess2;//玩家棋子id
    //下面3个参数用于人机后手下的第一步
    protected int sum=0;//敌方棋子数量
    protected int startX;
    protected int startY;
    //棋型对应的估值
    protected Map<String, Integer> chessTypes = new LinkedHashMap<>() {{
        put("11111", 4000000);
        put("011110", 300000);
        put("11101", 3000);
        put("0011100", 3000);
        put("10111", 3000);
        put("11011", 2600);
        put("11110", 2500);
        put("01111", 2500);
        put("010110", 2000);
        put("011010", 2000);
        put("00011000", 650);
        put("10011", 600);
        put("11001", 600);
        put("10101", 550);
        put("11100", 500);
        put("00111", 500);
        put("0010100", 250);
        put("010010", 200);
        put("11000", 150);
        put("00011", 150);
    }};
    protected int[][] nexts = new int[chessTypes.size()][];//用于kmp算法
    public abstract int run(int[][] map);//计算下次下的坐标x,y,返回值为当前得分
    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
    public int getChess(){return chess;}
    protected boolean changeMap(){//改变map,并且返回棋盘是否有棋子
        boolean v=false;
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                if(map[i][j]==chess){
                    v=true;
                    map[i][j]=1;
                }else if(map[i][j]!=0){
                    v=true;
                    sum++;
                    startX=i;
                    startY=j;
                    chess2=map[i][j];
                    map[i][j]=-1;
                }
            }
        }
        return v;
    }
    protected void recoverMap(){//还原map
        for(int i=0;i<N;i++){
            for(int j=0;j<N;j++){
                if(map[i][j]==1){
                    map[i][j]=chess;
                }else if(map[i][j]==-1){
                    map[i][j]=chess2;
                }
            }
        }
    }
    protected void buildNext(){//初始化nexts,用于kmp算法
        int k=0;
        for (String key : chessTypes.keySet()) {
            int n=key.length();
            nexts[k] = new int[n];
            nexts[k][0]=0;
            int prefix=0;
            int i=1;
            while(i<n){
                if(key.charAt(prefix)==key.charAt(i)){
                    prefix++;
                    nexts[k][i]=prefix;
                    i++;
                }else{
                    if(prefix==0){
                        nexts[k][i]=0;
                        i++;
                    }else{
                        prefix=nexts[k][prefix-1];
                    }
                }
            }
            k++;
        }
    }
    protected int getScore(String s){//寻找是否有符合棋型,返回得分
        int k=0;
        for (Map.Entry<String, Integer> chessType : chessTypes.entrySet()) {
            if(kmp(s,chessType.getKey(),k)){//使用kmp算法将时间复杂度降为m+n
                return chessType.getValue();
            }
            k++;
        }
        return 0;
    }
    protected boolean kmp(String s,String s2,int k){//kmp算法,判断该方向是否包含得分棋型
        int i=0;
        int j=0;
        int n=s.length();
        int m=s2.length();
        while (i<n){
            if(s.charAt(i)==s2.charAt(j)){
                i++;
                j++;
            }else if(j>0){
                j=nexts[k][j-1];
            }else{
                i++;
            }
            if(j==m){
                return true;
            }
        }
        return false;
    }
}
